<?php
###
#  Baing PHP 框架 1.0.0
#  http://baing.co/
#
#  Copyright: 白晓阳
#  License: CC BY-NC-SA 4.0
#  https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh
###

namespace bai;

use bai\feature\Agent;
use bai\resource\application\Logger, bai\resource\document\Config;


abstract class Baing
{
    use \bai\feature\Runnable;

    public const GET = 'GET';
    public const POST = 'POST';
    public const PUT = 'PUT';
    public const PATCH = 'PATCH';
    public const DELETE = 'DELETE';
    public const OPTIONS = 'OPTIONS';
    public const REST = [
        Request::GET,
        Request::POST,
        Request::PATCH,
        Request::DELETE
    ];

    protected static ?Request $request = null;
    protected static ?Response $response = null;
    protected static ?Process $process = null;
    protected static ?Logger $logger = null;

    final protected static function config($path)
    {
        return Agent::config($path);
    }

    final protected static function className(?string $fullName = null): string
    {
        $fullName ??= static::class;
        $pos = strrpos($fullName, '\\');
        return $pos === false ? $fullName : substr($fullName, $pos + 1);
    }

    final protected static function loadClass(string $className, array $runtime = [], string $type = null): ?self
    {
        if (str_contains($className, '\\')) {
            if (!$type || is_subclass_of($className, $type)) {
                return new $className($runtime);
            }
            return null;
        }

        $list = self::config("autoload.map.$className");
        if (!$list || !is_array($list)) return null;

        $fullName = null;
        if ($type) {
            foreach ($list as $item) {
                if (is_subclass_of($item, $type)) {
                    $fullName = $item;
                    break;
                }
            }
            if (!$fullName) return null;
        } else {
            $fullName = reset($list);
        }

        if (is_subclass_of($fullName, '\bai\Resource')) {
            return $fullName::setup($runtime);
        }
        return new $fullName($runtime);
    }

    protected function __construct(array $runtime = [])
    {
        if ($runtime) {
            $this->runtime = array_replace_recursive($this->runtime, $runtime);
        }
        if (($this->find('configurable') ?? true) && ($config = Config::load(static::class))) {
            $this->runtime = array_replace_recursive($config, $this->runtime);
        }
        $this->init();
    }

    protected function init()
    {
    }
}
